/*
 * Copyright (c) 2024 Black Sesame Technologies
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <thread>
#include <typeinfo>

#include <fastdds/dds/domain/DomainParticipantFactory.hpp>
#include <fastdds/dds/domain/DomainParticipant.hpp>
#include <fastdds/dds/topic/TypeSupport.hpp>
#include <fastdds/dds/publisher/Publisher.hpp>
#include <fastdds/dds/publisher/DataWriter.hpp>
#include <fastdds/dds/publisher/DataWriterListener.hpp>
#include <fastdds/dds/subscriber/Subscriber.hpp>
#include <fastdds/dds/subscriber/DataReader.hpp>
#include <fastdds/dds/subscriber/DataReaderListener.hpp>
#include <fastdds/dds/subscriber/qos/DataReaderQos.hpp>
#include <fastdds/dds/subscriber/SampleInfo.hpp>

#include "dal_msg/dalidl_runtime_c/message_type_support_struct.h"
#include "dalidl_typesupport_fastrtps_cpp/identifier.hpp"
#include "dal_fastrtps_cpp/type_support_common.hpp"

#include "mj_interfaces/msg/mjtype.hpp"
#include "fastdds_pubsub.hpp"

using namespace eprosima::fastdds::dds;

#define DAL_FASTRTPS_CPP_TYPESUPPORT_CPP dalidl_typesupport_fastrtps_cpp::typesupport_identifier

extern "C" {
extern const dalidl_message_type_support_t * 
    dalidl_typesupport_cpp__get_message_type_support_handle__mj_interfaces__msg__Mjtype();
}

const dalidl_message_type_support_t *GetTypeSupport()
{
    const dalidl_message_type_support_t &type_supports = get_message_type_support_handle<mj_interfaces::msg::Mjtype>();
    const dalidl_message_type_support_t *type_support = get_message_typesupport_handle(
        &type_supports, DAL_FASTRTPS_CPP_TYPESUPPORT_CPP);
    return type_support;
}

const dalidl_message_type_support_t *GetTypeSupport2()
{
    const dalidl_message_type_support_t *type_supports = 
        dalidl_typesupport_cpp__get_message_type_support_handle__mj_interfaces__msg__Mjtype();
    const dalidl_message_type_support_t *type_support = get_message_typesupport_handle(
        type_supports, DAL_FASTRTPS_CPP_TYPESUPPORT_CPP);
    return type_support;
}

int main(int argc, char **argv)
{
    // Create RTPSParticipant
    DomainParticipant *participant = DomainParticipantFactory::get_instance()->create_participant(20, PARTICIPANT_QOS_DEFAULT);
    if (!participant)
    {
        std::cout << "participant is null";
        return 1;
    }

    Publisher *publisher = participant->create_publisher(PUBLISHER_QOS_DEFAULT);
    if (!publisher)
    {
        std::cout << "publisher is null";
        return 1;
    }

    Subscriber *subscriber = participant->create_subscriber(SUBSCRIBER_QOS_DEFAULT);
    if (!subscriber)
    {
        std::cout << "subscriber is null";
        return 1;
    }

    const dalidl_message_type_support_t *type_support = GetTypeSupport();
    if (!type_support)
    {
        std::cout << "type_support is null";
        return 1;
    }

    auto callbacks = static_cast<const message_type_support_callbacks_t *>(type_support->data);
    std::string type_name = _create_type_name(callbacks);
    auto tsupport = new (std::nothrow) MessageTypeSupport_cpp(callbacks);
    TypeSupport fastdds_type(tsupport);

    if (ReturnCode_t::RETCODE_OK != fastdds_type.register_type(participant))
    {
        std::cout << "create_publisher() failed to register type";
        return 1;
    }

    Topic *topic = participant->create_topic("Mj_Topic", type_name, TOPIC_QOS_DEFAULT);
    if (!topic)
    {
        std::cout << "topic is null";
        return 1;
    }

    DataWriter *writer = publisher->create_datawriter(topic, DATAWRITER_QOS_DEFAULT, nullptr);
    if (!writer)
    {
        std::cout << "writer is null";
        return 1;
    }

    SubListener listener_;
    listener_.ts_callbacks_ = callbacks;
    DataReader *reader = subscriber->create_datareader(topic, DATAREADER_QOS_DEFAULT, &listener_);

    mj_interfaces::msg::Mjtype mj_type;
    mj_type.str = "mjtype";


    std::cout << typeid(mj_type).name() << std::endl;
    dal_fastrtps_shared_cpp::SerializedData data;
    data.is_cdr_buffer = false;
    data.data = static_cast<void *>(&mj_type);
    data.impl = callbacks;
    while (1)
    {
        mj_type.i8 += 1;
        mj_type.i16 += 1;
        writer->write(&data);
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }

    return 0;
}